/**************************************************************************************************
 *****                                                                                        *****
 *****  Name: I2C_busreset.cpp                                                          *****
 *****  Date: 24/11/2013                                                                      *****
 *****  Auth: Frank Vannieuwkerke                                                             *****
 *****  Func: library for unblocking I2C bus on KL25Z board                                   *****
 *****  Info: MPL3115A2-AN4481                                                                *****
 **************************************************************************************************/

#include "I2C_busreset.h"

void I2C_busreset(void)
{
    if((PORTE->PCR[1] & PORT_PCR_MUX(6)) && (PORTE->PCR[0] & PORT_PCR_MUX(6)))
    {
        I2C1->C1 &= 0x7f;                 // Disable I2C1 bus
        PORTE->PCR[1] = PORT_PCR_MUX(1);  // PTE1 Alt1 (pin)
        PORTE->PCR[0] = PORT_PCR_MUX(1);  // PTE0 Alt1 (pin)
        if((PTE->PDIR & 0x3) != 3)        // When PTE0 / PTE1 are not 1 : I2C1 bus lock-up
        {
            PTE->PDDR |= 0x2;             // Set PTE1 as a GPIO output so we can bit bang it
            PTE->PDOR |= 0x2;             // Set PTE1 (SCL) pin high;
            wait_ms(1);
            while(!(PTE->PDIR & 0x1))     // bit bang SCL until the offending device releases the bus
            {   
                PTE->PDOR &= 0xfffffffd;  // Set PTE1 (SCL) pin low;
                wait_ms(1);
                PTE->PDOR |= 0x2;         // Set PTE1 (SCL) pin high;
                wait_ms(1);
            }
        }
        // Reinstate I2C1 bus pins
        PORTE->PCR[1] = PORT_PCR_MUX(6);  // PTE1 Alt6 (SCL)
        PORTE->PCR[0] = PORT_PCR_MUX(6);  // PTE0 Alt6 (SDA)
        I2C1->C1 |= 0x80;                 // Enable I2C1 bus
    }

    if((PORTE->PCR[24] & PORT_PCR_MUX(5)) && (PORTE->PCR[25] & PORT_PCR_MUX(5)))
    {
        I2C0->C1 &= 0x7f;                 // Disable I2C0 bus
        PORTE->PCR[24] = PORT_PCR_MUX(1); // PTE24 Alt1 (pin)
        PORTE->PCR[25] = PORT_PCR_MUX(1); // PTE25 Alt1 (pin)
        if((PTE->PDIR & 0x03000000) != 0x03000000)  // When PTE24 / PTE25 are not 1 : I2C0 bus lock-up
        {
            PTE->PDDR |= 0x01000000;      // Set PTE24 as a GPIO output so we can bit bang it
            PTE->PDOR |= 0x01000000;      // Set PTE24 (SCL) pin high;
            wait_ms(1);
            while(!(PTE->PDIR & 0x1))     // bit bang SCL until the offending device releases the bus
            {   
                PTE->PDOR &= 0xfeffffff;  // Set PTE24 (SCL) pin low;
                wait_ms(1);
                PTE->PDOR |= 0x01000000;  // Set PTE24 (SCL) pin high;
                wait_ms(1);
            }
        }
        // Reinstate I2C0 bus pins
        PORTE->PCR[24] = PORT_PCR_MUX(5); // PTE24 Alt6 (SCL)
        PORTE->PCR[25] = PORT_PCR_MUX(5); // PTE25 Alt6 (SDA)
        I2C0->C1 |= 0x80;                 // Enable I2C0 bus
    }
}
